using System;

namespace PDUConverter
{
    /// <summary>
    /// Performs various numerical conversions and calculations.
    /// </summary>
    public class Calc
    {
        private static char[] hexDigits = new char[] { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };

        /// <summary>
        /// Converts a bit string into a byte.
        /// </summary>
        /// <param name="s">The string to convert.</param>
        /// <returns>The converted value.</returns>
        public static byte BinToInt(string s)
        {
            return Convert.ToByte(s, 2);
        }

        /// <summary>
        /// Converts a BCD encoded string (hexadecimal) into its byte representation.
        /// </summary>
        /// <param name="s">The string to convert.</param>
        /// <remarks>
        /// The length of the string should be even. This is not checked
        /// here to be able to process truncated strings.
        /// </remarks>
        /// <returns>The converted value.</returns>
        /// <example>
        /// <para>A string containing "41" will become {0x41}, which equals
        /// the character 'A'.</para>
        /// <para>A string containing "414242" will become {0x41, 0x42, 0x43}
        /// which equals the string "ABC".</para>
        /// </example>
        public static byte[] HexToInt(string s)
        {
            byte[] buffer = new byte[s.Length / 2];
            for (int i = 0; i < (s.Length / 2); i++)
            {
                string str = s.Substring(i * 2, 2);
                buffer[i] = Convert.ToByte(str, 0x10);
            }
            return buffer;
        }

        /// <summary>
        /// Converts a byte into a bit string.
        /// </summary>
        /// <param name="b">The byte to convert.</param>
        /// <param name="size">
        /// The final length the string should have. If the resulting string is
        /// shorter than this value, it is padded with leading zeroes.
        /// </param>
        /// <returns>The converted value.</returns>
        public static string IntToBin(byte b, byte size)
        {
            return Convert.ToString(b, 2).PadLeft(size, '0');
        }

        /// <summary>
        /// Converts a byte array into its hexadecimal representation (BCD encoding).
        /// </summary>
        /// <param name="bytes">The byte array to convert.</param>
        /// <returns>The converted value.</returns>
        public static string IntToHex(byte[] bytes)
        {
            char[] chArray = new char[bytes.Length * 2];
            for (int i = 0; i < bytes.Length; i++)
            {
                int num2 = bytes[i];
                chArray[i * 2] = hexDigits[num2 >> 4];
                chArray[(i * 2) + 1] = hexDigits[num2 & 15];
            }
            return new string(chArray);
        }

        /// <summary>
        /// Converts a byte into its BCD (hexadecimal) representation.
        /// </summary>
        /// <param name="b">The byte to convert.</param>
        /// <returns>The converted value.</returns>
        public static string IntToHex(byte b)
        {
            return (hexDigits[b >> 4].ToString() + hexDigits[b & 15].ToString());
        }

        /// <summary>
        /// Converts a byte array into its hexadecimal representation (BCD encoding).
        /// </summary>
        /// <param name="bytes">The byte array to convert.</param>
        /// <param name="index">The starting index of the byte array to convert.</param>
        /// <param name="count">The number of bytes to convert.</param>
        /// <returns>The converted value.</returns>
        public static string IntToHex(byte[] bytes, int index, int count)
        {
            char[] chArray = new char[count * 2];
            for (int i = 0; i < count; i++)
            {
                int num2 = bytes[index + i];
                chArray[i * 2] = hexDigits[num2 >> 4];
                chArray[(i * 2) + 1] = hexDigits[num2 & 15];
            }
            return new string(chArray);
        }

        /// <summary>
        /// Determines if a string is a hexadecimal character.
        /// </summary>
        /// <param name="c">The character to check.</param>
        /// <returns>true if the character is a hex char, false otherwise.</returns>
        public static bool IsHexDigit(char c)
        {
            char ch = char.ToUpper(c);
            foreach (char ch2 in hexDigits)
            {
                if (ch == ch2)
                {
                    return true;
                }
            }
            return false;
        }

        /// <summary>
        /// Determines if a string consists only of hexadecimal characters.
        /// </summary>
        /// <param name="s">The string to check.</param>
        /// <returns>true if the string is a hex string, false otherwise.</returns>
        public static bool IsHexString(string s)
        {
            if (s.Length == 0)
            {
                return false;
            }
            for (int i = 0; i < s.Length; i++)
            {
                if (!IsHexDigit(s[i]))
                {
                    return false;
                }
            }
            return true;
        }
    }
}